package com.khoayang.littlefighterchaos.game;

import java.util.ArrayList;
import java.util.Random;

import org.cocos2d.types.CGPoint;

import android.util.Log;

import com.khoayang.littlefighterchaos.game.GamePad.KEY;

public class IntelligentAI extends AI {

	private AttackingSkill _AttackingSkill;
	private boolean _Attacking = false;
	private Random _RandomGenerator;

	public IntelligentAI(CharacterGame character,
			ArrayList<CharacterGame> otherCharacters) {
		super(character, otherCharacters);
		_AttackingSkill = randomAAttackingSkill();
		_RandomGenerator = new Random();
		MAX_ATTACK_SKILL_DURATION = 50;
	}

	@Override
	public void update() {
		_Time ++;
		if(_Time > 100)
			_Time = 0;
//		Log.w("T", Integer.toString(_Time));
//		Log.w("Duration", Integer.toString(_AttackSkillDuration));
		CharacterGame enemyCharacter = findOneEnemy();
		if(enemyCharacter == null)
			return;
		
		if(_Time == _AttackSkillDuration){
			_AttackingSkill = randomAAttackingSkill();
			_Attacking  = true;
		}
		if (enoughEnergyToAttack(_AttackingSkill) && _Attacking) {
			attack(enemyCharacter, _AttackingSkill);
		}else{
			runAwayFrom(enemyCharacter);
		}
		_Character.update(new ArrayList<GamePad.KEY>());
	}

	private AttackingSkill randomAAttackingSkill() {
		ArrayList<AttackingSkill> attackingSkillList = new ArrayList<AttackingSkill>();
		for (int i = 0; i < _Character.get_State().get_SkillList().size(); i++) {
			BaseSkill skill = _Character.get_State().get_SkillList().get(i);
			if (skill instanceof AttackingSkill) {
				attackingSkillList.add((AttackingSkill) skill);
			}
		}

		Random randomGenerator = new Random();
		int i = randomGenerator.nextInt(attackingSkillList.size());
		return attackingSkillList.get(i);
	}

	private void runAwayFrom(CharacterGame enemyCharacter) {
		float distanceX = _Character.get_Position().x
				- enemyCharacter.get_Position().x;
		float distanceY = _Character.get_Position().y
				- enemyCharacter.get_Position().y;
		
		CGPoint pos = _Character.get_Position();
		
		moveHor(distanceX, pos);
		randomMoveVer(distanceY, pos);

	}

	private void randomMoveVer(float distanceY, CGPoint pos) {
		if(pos.y >= _WinSize.height/3){
			moveDown();
		}else if(pos.y <= _Character.get_Sprite().getContentSize().getHeight()/2){
			moveUp();
		}
	}

	private void moveHor(float distanceX, CGPoint pos) {
		if (distanceX < 0) {
			if(pos.x >= 0){
				moveToLeft();
			}
		}else{
			if(pos.x <= _WinSize.width){
				moveToRight();
			}
		}
	}

	private void attack(CharacterGame enemyCharacter,
			AttackingSkill attackingSkill) {
		moveToAndAttack(enemyCharacter, attackingSkill);
	}

	private void moveToAndAttack(CharacterGame enemyCharacter,
			AttackingSkill attackingSkill) {
		int attackDistanceX = 50;
		if(attackingSkill.get_AttackingObjects().size() > 0)
			attackDistanceX = 250;
		int attackDistanceY = 5;
		float distanceX = _Character.get_Position().x
				- enemyCharacter.get_Position().x;
		float distanceY = _Character.get_Position().y
				- enemyCharacter.get_Position().y;
		if (Math.abs(distanceX) > attackDistanceX
				|| Math.abs(distanceY) > attackDistanceY) {
			if (distanceX > 0) {
				moveToLeft();
			} else {
				moveToRight();
			}
			if (distanceY < 0) {
				moveUp();
			} else {
				moveDown();
			}

		} else {
			if(!(_Character.get_State().get_CurrentSkill() instanceof AttackingSkill)){
				if (distanceX > 0) {
					moveToLeft();
				} else {
					moveToRight();
				}
				_Character.startAction(attackingSkill.get_SkillName());
				_AttackSkillDuration = _RandomGenerator.nextInt(MAX_ATTACK_SKILL_DURATION);
				_Time = 0;
				_Attacking = false;
			}
		}

	}

	private void moveDown() {
		KEY key = KEY.DOWN;
		moveToDirection(key);
	}

	private void moveUp() {
		KEY key = KEY.UP;
		moveToDirection(key);
	}

	private void moveToRight() {
		KEY key = KEY.RIGHT;
		moveToDirection(key);
	}

	private void moveToLeft() {
		KEY key = KEY.LEFT;
		moveToDirection(key);
	}

	private void moveToDirection(KEY key) {
		ArrayList<KEY> keyState = new ArrayList<GamePad.KEY>();
		keyState.add(key);
		if(_Character.get_State().get_CurrentSkill() != null){
			if(_Character.get_State().get_CurrentSkill().get_SkillName().compareTo("Walk") != 0)
				_Character.startAction("Walk");
		}else{
			_Character.startAction("Walk");
		}
		_Character.update(keyState);
	}

	private boolean enoughEnergyToAttack(AttackingSkill skill) {
		if (_Character.skillReady(skill.get_SkillName())) {
			return true;
		}
		return false;
	}

	private CharacterGame findOneEnemy() {
		ArrayList<CharacterGame> enemyList = new ArrayList<CharacterGame>();
		for (int i = 0; i < _OtherCharacters.size(); i++) {
			if (_Character.get_ID() != _OtherCharacters.get(i).get_ID()) {
				enemyList.add(_OtherCharacters.get(i));
			}
		}
		return findNearestEnemy(enemyList);
	}

	private CharacterGame findNearestEnemy(ArrayList<CharacterGame> enemyList) {
		ArrayList<Float> distances = new ArrayList<Float>();
		for(int i=0; i<enemyList.size(); i++)
		{
			distances.add(calculateDistance(_Character.get_Position(), enemyList.get(i).get_Position()));
		}
		if(distances.size() == 0) 
			return null;
		float minDis = distances.get(0);
		int minIndex = 0;
		for(int i=0; i<distances.size(); i++){
			if(minDis > distances.get(i)){
				minDis = distances.get(i);
				minIndex = i;
			}
		}
		return enemyList.get(minIndex);
	}

	private Float calculateDistance(CGPoint cgPoint, CGPoint cgPoint2) {
		return CGPoint.ccpDistance(cgPoint, cgPoint2);
	}

}
